package com.az.order.service.impl;

import com.az.miaoapi.dto.Address;
import com.az.miaoapi.dto.Product;
import com.az.miaoapi.dto.Type;
import com.az.miaoapi.exception.BaseException;
import com.az.miaoapi.feign.ItemClient;
import com.az.miaoapi.feign.PayClient;
import com.az.miaoapi.feign.UserClient;
import com.az.miaoapi.response.ResponseCode;
import com.az.miaoapi.vo.Null;
import com.az.miaoapi.vo.TheVo;
import com.az.order.domain.dto.OrderSearchDto;
import com.az.order.domain.po.OrderDetail;
import com.az.order.domain.po.Orders;
import com.az.order.domain.vo.OrderVo;
import com.az.order.domain.vo.OrderVoList;
import com.az.order.mapper.OrdersMapper;
import com.az.order.service.OrderDetailService;
import com.az.order.service.OrdersService;
import com.az.order.util.OrderUtils;
import com.az.rediscommon.util.RedissonLockUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.aop.framework.AopContext;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.retry.annotation.Retryable;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;


import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author zj
 * @time 2024/8/23 23:13
 */
@Service
@Slf4j
public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Orders> implements OrdersService {

    @Resource
    private OrdersMapper ordersMapper;

    @Resource
    private OrderDetailService orderDetailService;

    @Resource
    private ItemClient itemClient;

    @Resource
    private PayClient payClient;

    @Resource
    private UserClient userClient;

    @Resource
    private OrderUtils orderUtils;


    /**
     * 查询订单
     * @param orderSearchDto
     * @param userId
     * @return
     */
    @Override
    @Retryable(noRetryFor = BaseException.class)
    @PreAuthorize("hasAnyAuthority({'loginUser'})")
    @Cacheable(value = "orders", key = "#userId + #orderSearchDto.state + #orderSearchDto.time +#orderSearchDto.name")
    public OrderVoList getOrder(OrderSearchDto orderSearchDto, Long userId) {
        // 1.构建查询条件 查询订单
        QueryWrapper<Orders> orderQueryWrapper = buildOrderQueryWrapper(orderSearchDto, userId);
        List<Orders> orderList = ordersMapper.selectList(orderQueryWrapper);
        // 2.收集所有相关ID
        List<Integer> productIds = orderUtils.collectProductIds(orderList);
        List<Long> orderIds =orderUtils. collectOrderIds(orderList);
        List<Integer> addressIds = orderUtils.collectAddressIds(orderList);
        List<Integer> typeIds = orderUtils.collectTypeIds(orderList);
        // 3.批量查询信息,避免频繁远程调用
        Map<Integer, Type> typeMap = itemClient.batchGetTypeByIds(typeIds);
        Map<Integer, Product> productMap = itemClient.batchGetProductsByIds(productIds);
        Map<Integer, Address> addressMap = userClient.batchGetAddressesByIds(addressIds);
        // 4.封装VO
        List<OrderVo> orderVos = new ArrayList<>();
        for (Orders order : orderList) {
            //4.1 设置订单vo信息
            OrderVo orderVo = new OrderVo();
            orderVo.setOrderId(order.getOrderId());
            orderVo.setDate(order.getOrderTime());
            int state1 = order.getStatus();
            if (state1 == 1) {
                orderVo.setState("已支付");
            } else {
                orderVo.setState("未支付");
            }
            orderVo.setConsignee(order.getConsignee());
            orderVo.setAmount(order.getPrices());
            Long orderId =order.getOrderId();
            List<String> types = new ArrayList<>();
            // 4.2 获取订单型号信息
            List<OrderDetail> orderDetails = orderUtils.getOrderDetails(orderId);
            List<OrderDetail> orderDetailList = orderUtils.getOrderDetails(orderId);
            for (OrderDetail orderDetail : orderDetailList) {
                Integer typeId = orderDetail.getTypeId();
                Type type = typeMap.get(typeId);
                if (type == null) {
                    throw new BaseException(ResponseCode.NO_THIS_TYPE);
                }
                types.add(type.getTypeName());
            }
            orderVo.setType(types);
            // 4.3 获取商品名称及图像
            OrderDetail detail = orderDetailList.get(0);
            Integer productId = detail.getProductId();
            Product product = productMap.get(productId);
            if (product == null) {
                throw new BaseException(ResponseCode.NO_PRODUCT);
            }
            orderVo.setProductName(product.getProductName());
            orderVo.setImage(product.getImage());
            // 4.4 获取地址信息
            Integer addressId = order.getAddressId();
            Address address = addressMap.get(addressId);
            if (address == null) {
                throw new BaseException(ResponseCode.NO_ADDRESS);
            }
            orderVo.setAddress(address.getDetail());
            // 4.5 封装VO列表
            orderVos.add(orderVo);
        }
        log.info("查询成功");
        OrderVoList orderVoList = new OrderVoList();
        orderVoList.setOrderVoList(orderVos);
        return orderVoList;
    }

    private QueryWrapper<Orders> buildOrderQueryWrapper(OrderSearchDto orderSearchDto, Long userId) {
        QueryWrapper<Orders> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);
        Integer state = orderSearchDto.getState();
        Integer time = orderSearchDto.getTime();
        String name = orderSearchDto.getName();

        if (state == 1 || state == 2) {
            queryWrapper.eq("status", state);
        }

        LocalDateTime now = LocalDateTime.now();
        LocalDateTime startTime;
        if (time != 1) {
            if (time == 2) { // 近半年
                startTime = now.minusMonths(6);
            } else { // 近三个月
                startTime = now.minusMonths(3);
            }
            Date startDate = Date.from(startTime.atZone(ZoneId.systemDefault()).toInstant());
            queryWrapper.ge("shipping_time", startDate);
        }

        // 产品名模糊查询
        List<Product> productList = itemClient.listProductByName(name);
        if (productList.isEmpty()) {
            throw new BaseException(ResponseCode.NO_PRODUCT);
        }

        List<Integer> productIds = productList.stream()
                .map(Product::getProductId)
                .collect(Collectors.toList());

        if (!productIds.isEmpty()) {
            QueryWrapper<OrderDetail> orderDetailQueryWrapper = new QueryWrapper<>();
            orderDetailQueryWrapper.in("product_id", productIds);
            List<OrderDetail> orderDetails = orderDetailService.list(orderDetailQueryWrapper);
            List<Integer> orderIds = orderDetails.stream()
                    .map(OrderDetail::getOrderId)
                    .collect(Collectors.toList());
            if (orderIds.isEmpty()) {
                throw new BaseException(ResponseCode.NOT_FIND_ORDER);
            }
            queryWrapper.in("order_id", orderIds);
        }

        return queryWrapper;
    }


    /**
     * 支付订单
     * @param orderId
     * @param userId
     * @return
     */
    @Override
    @Retryable(noRetryFor = BaseException.class)
    @PreAuthorize("hasAnyAuthority({'loginUser'})")
    public TheVo postOrders(Long orderId, Long userId) {
        //1. 查询订单信息
        QueryWrapper<Orders> orderQueryWrapper = new QueryWrapper<>();
        orderQueryWrapper.eq("order_id", orderId);
        Orders order = ordersMapper.selectOne(orderQueryWrapper);
        //2. 检查用户名是否与当前登录用户匹配
        if (order == null || !order.getUserId().equals(userId)) {
            throw new BaseException(ResponseCode.ORDER_STATUS_EXCEPTION);
        }
        //2.1 检查订单状态
        if(order.getStatus() == 1) throw new BaseException(ResponseCode.ORDER_STATUS_EXCEPTION);
        // 3. 检验库存并扣减库存
        List<OrderDetail> orderDetails = orderUtils.getOrderDetails(orderId);
        // 3.1 使用一个 Map 聚合每种 typeId 的总数量
        Map<Integer, Integer> typeCountMap = new HashMap<>();
        // 3.2获取第一个 OrderDetail 的 productId
        Integer productId = orderDetails.get(0).getProductId();

        try {
            // 3.3 删减库存
            RedissonLockUtil.getInstance().lock("ordPay"+orderId);
            boolean stock  = itemClient.deductInventory(typeCountMap,productId);
            if (!stock) throw new BaseException(ResponseCode.LACK_PRODUCT_ERROR);
            BigDecimal money = order.getPrices();
            // 4.进行支付操作
            Boolean paySuccess = payClient.processPayment(money);
            if (!paySuccess) {
                throw new BaseException(ResponseCode.PAY_FAILED);
            }
            //5.支付成功后更新订单状态
            order.setStatus(1); // 设置状态为支付成功
            ordersMapper.updateById(order);

        }finally {
            RedissonLockUtil.getInstance().unLock("ordPay"+orderId);
        }
        log.info("购买成功");
        userClient.setLikenessStatusToBuy(userId,productId);
        return new Null();
    }


}

